import JsDataStore from './JsDataStore'
import { BusinessError } from '@ohos.base';
import inputMethod from '@ohos.inputMethod';
import inputMethodEngine from '@ohos.inputMethodEngine';

export class JsInputMethod {
  private handler: number = 0;
  private attached: boolean = false;
  private inputMethodController: inputMethod.InputMethodController = inputMethod.getController();

  public constructor() {
  }

  private subscribe() {
    try {
      this.inputMethodController.on('insertText', (text: string) => {
        console.info('Succeeded in getting callback1 data: ' + JSON.stringify(text));
        JsDataStore.getQtNativeModule("QPA").insertText(this.handler, text);
      });
    } catch (err) {
      console.error(`Failed to subscribe insertText: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('deleteLeft', (length: number) => {
        console.log(`Succeeded in subscribing deleteLeft, length: ${length}`);
        JsDataStore.getQtNativeModule("QPA").deleteLeft(this.handler, length);
      });
    } catch (err) {
      console.error(`Failed to subscribe deleteLeft: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('deleteRight', (length: number) => {
        console.log(`Succeeded in subscribing deleteRight, length: ${length}`);
        JsDataStore.getQtNativeModule("QPA").deleteRight(this.handler, length);
      });
    } catch (err) {
      console.error(`Failed to subscribe deleteRight: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('moveCursor', (direction: inputMethod.Direction) => {
        console.log(`Succeeded in subscribing moveCursor, direction: ${direction}`);
        JsDataStore.getQtNativeModule("QPA").moveCursor(this.handler, direction);
      });
    } catch (err) {
      console.error(`Failed to subscribe moveCursor: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('handleExtendAction', (action: inputMethod.ExtendAction) => {
        console.log(`Succeeded in subscribing handleExtendAction, action: ${action}`);
      });
    } catch (err) {
      console.error(`Failed to subscribe handleExtendAction: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('selectByRange', (range: inputMethod.Range) => {
        console.log(`Succeeded in subscribing selectByRange: start: ${range.start} , end: ${range.end}`);
      });
    } catch (err) {
      console.error(`Failed to subscribe selectByRange: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('selectByMovement', (movement: inputMethod.Movement) => {
        console.log('Succeeded in subscribing selectByMovement: direction: ' + movement.direction);
      });
    } catch (err) {
      console.error(`Failed to subscribe selectByMovement: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('getLeftTextOfCursor', (length: number) => {
        console.info(`Succeeded in subscribing getLeftTextOfCursor, length: ${length}`);
        let text: string = "";
        return text;
      });
    } catch (err) {
      console.error(`Failed to unsubscribing getLeftTextOfCursor. err: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('getRightTextOfCursor', (length: number) => {
        console.info(`Succeeded in subscribing getRightTextOfCursor, length: ${length}`);
        let text: string = "";
        return text;
      });
    } catch (err) {
      console.error(`Failed to subscribe getRightTextOfCursor. err: ${JSON.stringify(err)}`);
    }

    try {
      this.inputMethodController.on('getTextIndexAtCursor', () => {
        console.info(`Succeeded in subscribing getTextIndexAtCursor.`);
        let index: number = 0;
        return index;
      });
    } catch (err) {
      console.error(`Failed to subscribe getTextIndexAtCursor. err: ${JSON.stringify(err)}`);
    }
  }

  private unsubscribe() {
    this.inputMethodController.off('moveCursor');
    this.inputMethodController.off('insertText');
    this.inputMethodController.off('deleteLeft');
    this.inputMethodController.off('deleteRight');
    this.inputMethodController.off('selectByRange');
    this.inputMethodController.off('selectByMovement');
    this.inputMethodController.off('handleExtendAction');
    this.inputMethodController.off('getLeftTextOfCursor');
    this.inputMethodController.off('getRightTextOfCursor');
    this.inputMethodController.off('getTextIndexAtCursor');
  }

  isAttached() {
    return this.attached;
  }

  attach(handler: number): boolean {
    if (true == this.attached) {
      return;
    }

    if (0 == handler) {
      console.error("handle number is error");
      return;
    }

    this.handler = handler;
    try {
      let textConfig: inputMethod.TextConfig = {
        inputAttribute: {
          textInputType: inputMethod.TextInputType.MULTILINE,
          enterKeyType: inputMethod.EnterKeyType.UNSPECIFIED
        }
      };
      this.inputMethodController.attach(true, textConfig).then(() => {
        this.subscribe();
        console.log('Succeeded in attaching inputMethod.');
      }).catch((err) => {
        console.error(`Failed to attach: ${JSON.stringify(err)}`);
        return false;
      })
    } catch (err) {
      console.error(`Failed to attach: ${JSON.stringify(err)}`);
    }
    this.attached = true;
  }

  detach() {
    this.unsubscribe();
    this.inputMethodController.detach().then(() => {
      console.log('Succeeded in detaching inputMethod.');
    }).catch((err) => {
      console.error(`Failed to detach: ${JSON.stringify(err)}`);
    });
    this.attached = false;
  }

  showTextInput() {
    this.inputMethodController.showTextInput().then(() => {
      console.log('Succeeded in showing text input.');
    }).catch((err) => {
      console.error(`Failed to showTextInput: ${JSON.stringify(err)}`);
    });
  }

  hideTextInput() {
    this.inputMethodController.hideTextInput().then(() => {
      console.log('Succeeded in hiding inputMethod.');
    }).catch((err) => {
      console.error(`Failed to hideTextInput: ${JSON.stringify(err)}`);
    });
  }

  setCallingWindow(windowId: number) {
    try {
      this.inputMethodController.setCallingWindow(windowId).then(() => {
        console.log('Succeeded in setting callingWindow.');
      }).catch((err) => {
        console.error(`Failed to setCallingWindow: ${JSON.stringify(err)}`);
      })
    } catch (err) {
      console.error(`Failed to setCallingWindow: ${JSON.stringify(err)}`);
    }
  }

  updateCursor(left: number, top: number, width: number, height: number) {
    try {
      let cursorInfo: inputMethod.CursorInfo = { left: left, top: top, width: width, height: height };
      this.inputMethodController.updateCursor(cursorInfo).then(() => {
        console.log('Succeeded in updating cursorInfo.');
      }).catch((err) => {
        console.error(`Failed to updateCursor: ${JSON.stringify(err)}`);
      })
    } catch (err) {
      console.error(`Failed to updateCursor: ${JSON.stringify(err)}`);
    }
  }

  changeSelection(text: string, start: number, end: number) {
    try {
      this.inputMethodController.changeSelection(text, start, end).then(() => {
        console.log('Succeeded in changing selection.');
      }).catch((err) => {
        console.error(`Failed to changeSelection: ${JSON.stringify(err)}`);
      })
    } catch (err) {
      console.error(`Failed to changeSelection: ${JSON.stringify(err)}`);
    }
  }

  stopInputSession() {
    try {
      this.inputMethodController.stopInputSession().then((result: boolean) => {
        if (result) {
          console.log('Succeeded in stopping inputSession.');
        } else {
          console.error('Failed to stopInputSession.');
        }
      }).catch((err) => {
        console.error(`Failed to stopInputSession: ${JSON.stringify(err)}`);
      })
    } catch (err) {
      console.error(`Failed to stopInputSession: ${JSON.stringify(err)}`);
    }
  }

  showSoftKeyboard() {
    this.inputMethodController.showSoftKeyboard().then(() => {
      console.log('Succeeded in showing softKeyboard.');
    }).catch((err: BusinessError) => {
      console.error(`Failed to show softKeyboard: ${JSON.stringify(err)}`);
    });
  }

  hideSoftKeyboard() {
    this.inputMethodController.hideSoftKeyboard().then(() => {
      console.log('Succeeded in hiding softKeyboard.');
    }).catch((err: BusinessError) => {
      console.error(`Failed to hide softKeyboard: ${JSON.stringify(err)}`);
    });
  }
}